package com.stx.jeepay.payment.controller.transfer;

import com.stx.jeepay.core.ctrls.AbstractCtrl;
import com.stx.jeepay.core.entity.TransferOrderEntity;
import com.stx.jeepay.core.expection.BizException;
import com.stx.jeepay.core.expection.ResponseException;
import com.stx.jeepay.core.service.TransferOrderService;
import com.stx.jeepay.core.utils.SpringBeansUtil;
import com.stx.jeepay.payment.channel.ITransferNoticeService;
import com.stx.jeepay.payment.model.MchAppConfigContext;
import com.stx.jeepay.payment.rqrs.msg.ChannelRetMsg;
import com.stx.jeepay.payment.service.ConfigContextQueryService;
import com.stx.jeepay.payment.service.PayMchNotifyService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

/**
 * 转账异步通知入口Controller
 */
@Slf4j
@Controller
public class TransferNoticeController extends AbstractCtrl {

    @Autowired
    private TransferOrderService transferOrderService;
    @Autowired
    private ConfigContextQueryService configContextQueryService;
    @Autowired
    private PayMchNotifyService payMchNotifyService;

    /**
     * 异步回调入口
     **/
    @ResponseBody
    @RequestMapping(value = {"/api/transfer/notify/{ifCode}", "/api/transfer/notify/{ifCode}/{transferId}"})
    public ResponseEntity doNotify(HttpServletRequest request, @PathVariable("ifCode") String ifCode,
                                   @PathVariable(value = "transferId", required = false) String urlOrderId) {
        String transferId = null;
        String logPrefix = "进入[" + ifCode + "]转账回调：urlOrderId：[" + StringUtils.defaultIfEmpty(urlOrderId, "") + "] ";
        log.info("===== {} =====", logPrefix);

        try {
            // 参数有误
            if (StringUtils.isEmpty(ifCode)) {
                return ResponseEntity.badRequest().body("ifCode is empty");
            }

            // 获取上游接口具体实现(微信或者支付宝)
            ITransferNoticeService transferNotifyService =
                    SpringBeansUtil.getBean(ifCode + "TransferNoticeService", ITransferNoticeService.class);

            // 上游支付实现不存在
            if (transferNotifyService == null) {
                log.error("{}, transfer interface not exists ", logPrefix);
                return ResponseEntity.badRequest().body("[" + ifCode + "] transfer interface not exists");
            }

            MutablePair<String, Object> mutablePair = transferNotifyService.parseParams(request, urlOrderId);
            if (mutablePair == null) {
                log.error("{}, mutablePair is null ", logPrefix);
                throw new BizException("解析数据异常！"); //需要实现类自行抛出ResponseException, 不应该在这抛此异常。
            }

            // 解析转账单号
            transferId = mutablePair.left;
            log.info("{}, 解析数据为：transferId:{}, params:{}", logPrefix, transferId, mutablePair.getRight());

            // 获取转账订单数据
            TransferOrderEntity transferOrder = transferOrderService.getById(transferId);

            // 转账订单不存在
            if (transferOrder == null) {
                log.error("{}, 转账单不存在. transferId={} ", logPrefix, transferId);
                return transferNotifyService.doNotifyOrderNotExists(request);
            }

            // 转账相关商户的配置数据和信息
            MchAppConfigContext mchAppConfigContext =
                    configContextQueryService.queryMchInfoAndAppInfo(transferOrder.getMchNo(), transferOrder.getAppId());

            // 调用上游接口实现进行通知
            ChannelRetMsg notifyResult =
                    transferNotifyService.doNotice(request, mutablePair.getRight(), transferOrder, mchAppConfigContext);

            // 返回结果为null 表示订单异常 无需用纸上游支付(不要去通知微信和支付宝)
            if (notifyResult == null || notifyResult.getChannelState() == null || notifyResult.getResponseEntity() == null) {
                log.error("{}, 处理回调事件异常  notifyResult data error, notifyResult ={} ", logPrefix, notifyResult);
                throw new BizException("处理回调事件异常！"); //需要实现类自行抛出ResponseException, 不应该在这抛此异常。
            }

            // 订单转账中
            if (transferOrder.getState() == TransferOrderEntity.STATE_ING) {
                if (notifyResult.getChannelState() == ChannelRetMsg.ChannelState.CONFIRM_SUCCESS) {
                    // 转账成功
                    transferOrderService.updateIng2Success(transferId, notifyResult.getChannelOrderId());
                    payMchNotifyService.transferOrderNotify(transferOrderService.getById(transferId));
                } else if (notifyResult.getChannelState() == ChannelRetMsg.ChannelState.CONFIRM_FAIL) {
                    // 转账失败
                    transferOrderService.updateIng2Fail(transferId, notifyResult.getChannelOrderId(), notifyResult.getChannelUserId(), notifyResult.getChannelErrCode());
                    payMchNotifyService.transferOrderNotify(transferOrderService.getById(transferId));
                }
            }

            log.info("===== {}, 转账单通知完成。 transferId={}, parseState = {} =====", logPrefix, transferId, notifyResult.getChannelState());
            return notifyResult.getResponseEntity();
        } catch (BizException e) {
            log.error("{}, transferId={}, BizException", logPrefix, transferId, e);
            return ResponseEntity.badRequest().body(e.getMessage());
        } catch (ResponseException e) {
            log.error("{}, transferId={}, ResponseException", logPrefix, transferId, e);
            return e.getResponseEntity();
        } catch (Exception e) {
            log.error("{}, transferId={}, 系统异常", logPrefix, transferId, e);
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }
}
